/*
 * Socket.cpp
 *
 *  Created on: 15/05/2011
 *      Author: dela
 */

#include "Socket.h"

#include <stdlib.h>
#include <string.h>
#include <netdb.h>
#include <sys/socket.h>
#include <iostream>

/**
 *
 */
Socket::Socket(int port) : stop(false) {
	struct sockaddr_in serv_addr;

	if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
		exit(1);
	}

	memset((char *) &serv_addr, 0, sizeof(serv_addr));
	serv_addr.sin_family = AF_INET;
	serv_addr.sin_port = htons(port);
	serv_addr.sin_addr.s_addr = INADDR_ANY;

	if (bind(sockfd, (struct sockaddr *) &serv_addr,
			(socklen_t) sizeof(struct sockaddr)) < 0) {
		exit(1);
	}

	listen(sockfd, 10);
}


/**
 *
 */
Socket::~Socket() {
	close(sockfd);
}


/**
 *
 */
void Socket::shutdownSocket() {
	stop = true;
	shutdown(sockfd, SHUT_RDWR);
}


/**
 *
 */
unsigned int Socket::acceptConnection() {
	struct sockaddr_in cli_addr;
	unsigned int clilen = (socklen_t) sizeof(cli_addr);
	return accept(sockfd, (struct sockaddr*) &cli_addr, &clilen);
}


/**
 *
 */
int Socket::connectSocket(char *ip, int port) {
	struct hostent *he;
	struct sockaddr_in their_addr;
	he = gethostbyname(ip);
	sockfd = socket(AF_INET, SOCK_STREAM, 0);
	their_addr.sin_family = AF_INET;
	their_addr.sin_port = htons(port);
	their_addr.sin_addr = *((struct in_addr *) he->h_addr);
	memset(&(their_addr.sin_zero), 8, sizeof(int));
	return connect(sockfd, (struct sockaddr *) &their_addr, sizeof(struct sockaddr));
}


/**
 *
 */
int Socket::receiveRepeat(unsigned int size, char *data) {
	unsigned int s = 0;
	int aux = 0;
	while (s < size && !stop) {
		aux = recv(sockfd, data+s, size-s, NULL);
		if (aux < 0) return -1;
		s += aux;
	}
	return s;
}


/**
 *
 */
int Socket::sendRepeat(unsigned int size, const char *data) {
	unsigned int s = 0;
	int aux = 0;
	while (s < size) {
		aux = send(sockfd, data+s, size-s, NULL);
		if (aux < 0) return -1;
		s += aux;
	}
	return s;
}


/**
 *
 */
int Socket::sendData(unsigned int size, const char *data) {
	if (sendRepeat(sizeof(unsigned int), (char *)&size) < 0)
		return -1;
	return sendRepeat(size, data);
}


/**
 *
 */
int Socket::receiveData(char **data) {
	unsigned int size = 0;
	receiveRepeat(sizeof(unsigned int), (char *) &size);
	*data = new char[size];
	return receiveRepeat(size, *data);
}





